package com.example.qxfw.qxybzz.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dmgis.entity.DmGridInfo;
import com.dmgis.service.DmServiceConnector;
import com.dmgis.util.DateTime;
import com.dmgis.weblib.GridAnalysis;
import com.example.qxfw.common.util.DocModelUtil;
import com.example.qxfw.qxybzz.entity.BaseProduct;
import com.example.qxfw.qxybzz.entity.HyDocFile;
import com.example.qxfw.qxybzz.entity.constantVo;
import com.example.qxfw.qxybzz.entity.constantfcst;
import com.example.qxfw.qxybzz.mapper.BaseProductMapper;
import com.example.qxfw.qxybzz.mapper.ServiceMaterialsMapper;
import com.example.qxfw.qxybzz.service.ServiceMaterialsService;
import org.apache.ibatis.datasource.DataSourceException;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.Envelope2D;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 14559
 * @version 1.0
 * @description: TODO
 * @date 2024/12/8 17:34
 */
@Service
public class ServiceMaterialsServiceImpl implements ServiceMaterialsService {

    @Value("${dmgis.ip}")
    private String dmgisIp;

    @Value("${dmgis.port}")
    private String dmgisPort;

    @Value("${dmgis.pluginpath}")
    private String pluginpath;

    @Value("${dmgis.image_url}")
    private String imgUrl;

    @Value("${dmgis.active}")
    private String active;

    @Resource
    private ServiceMaterialsMapper serviceMaterialsMapper;

    @Autowired
    private BaseProductMapper baseProductMapper;

    @Qualifier("mongoSecondTemplate")
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public ArrayList<Object> AnalyzeDat(File file, String originalFilename) {
        ArrayList<Object> arrayList = new ArrayList<>();
        // 创建 GeoTiffReader
        GeoTiffReader reader = null;
        try {
            reader = new GeoTiffReader(file);
            // 读取栅格数据
            GridCoverage2D coverage = reader.read(null);
            Envelope2D envelope = coverage.getEnvelope2D();
            // 获取栅格影像
            RenderedImage image = coverage.getRenderedImage();

            double minx = envelope.getMinX();
            double miny = envelope.getMinY();
            double maxx = envelope.getMaxX();
            double maxy = envelope.getMaxY();
            System.out.println("envelope minx: " + minx);
            System.out.println("envelope miny: " + miny);
            System.out.println("envelope maxx: " + maxx);
            System.out.println("envelope maxy: " + maxy);
            int matrixW = image.getWidth();
            int matrixH = image.getHeight();
            System.out.println("Image width: " + matrixW);
            System.out.println("Image height: " + matrixH);
            String urlgrid = pluginpath + "\\" + originalFilename.replace(".dat", ".grid");
            String gridpngpath = pluginpath + "\\" + originalFilename.replace(".dat", ".png");
            File gridfile = new File(urlgrid);
            File pngfile = new File(gridpngpath);
            if (!gridfile.exists() || !pngfile.exists()) {
                DmGridInfo dmGridInfo = new DmGridInfo();
                dmGridInfo.setRows(matrixH);
                dmGridInfo.setCols(matrixW);
                dmGridInfo.setxMin(minx);
                dmGridInfo.setxMax(maxx);
                dmGridInfo.setyMin(miny);
                dmGridInfo.setyMax(maxy);

                GridAnalysis gridAnalysis = new GridAnalysis();
                gridAnalysis.create(dmGridInfo, urlgrid);
                Raster raster = image.getData();
                for (int i = 0; i < matrixW; i++) {
                    for (int j = 0; j < matrixH; j++) {
                        int value = raster.getSample(i, j, 0);
                        if (value >= 9999)
                            value = -99999;
                        gridAnalysis.setValue(dmGridInfo.getRows() - 1 - j, i, value);
                    }
                }
                gridAnalysis.writeFile(urlgrid);
                //生成png图片
                ArrayList<Float> colorlist = new ArrayList<Float>();
                ArrayList<String> colors = new ArrayList<String>();
                colorlist.add((float) 1);
                colors.add("#91C3F4");
                colorlist.add((float) 6);
                colors.add("#0100FC");
                colorlist.add((float) 11);
                colors.add("#D8FBA9");
                colorlist.add((float) 16);
                colors.add("#29720E");
                colorlist.add((float) 21);
                colors.add("#E50B0A");
                colorlist.add((float) 31);
                colors.add("#8B0101");
                gridAnalysis.drawGridInfo(1, gridpngpath, colorlist, colors, 1);//绘制图片
            }

            //调用插件，生成图片
            String paramname = originalFilename.replace(".dat", "");
            arrayList.addAll(AnalysisJson(paramname, "xinjiangYili", "ylhg_m"));
            arrayList.addAll(AnalysisJson(paramname, "xinjiangKS", "KS"));
            arrayList.addAll(AnalysisJson(paramname, "xinjiangTKS", "TKS"));
        } catch (DataSourceException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 关闭 Reader
            reader.dispose();
        }
        return arrayList;
    }

    @Override
    public int updateConstantfcst(constantfcst cconstantfcst) {
        return serviceMaterialsMapper.updateConstantResult(cconstantfcst);
    }

    @Override
    public Object makeConstantDoc(String lyname, String datetime, String qishu, MultipartFile[] images) {//模板路径
        String templatePath;
        //产品路径
        String targetPath;

        ApplicationHome applicationHome = new ApplicationHome(this.getClass());
        if (active.equals("dev")) {
            templatePath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\templates\\积雪遥感监测专报模板.docx";
            targetPath = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() +
                    "\\src\\main\\resources\\temp\\积雪遥感监测专报.docx";
        } else {
            templatePath = applicationHome.getSource().getParentFile() +
                    "\\resources\\templates\\积雪遥感监测专报模板.docx";
            targetPath = applicationHome.getSource().getParentFile() +
                    "\\resources\\temp\\积雪遥感监测专报.docx";
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  // 指定日期格式
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd");  // 指定日期格式
        SimpleDateFormat sdfyear = new SimpleDateFormat("yyyy");  // 指定日期格式
        SimpleDateFormat sdfmonth = new SimpleDateFormat("MM");  // 指定日期格式
        SimpleDateFormat sdfday = new SimpleDateFormat("dd");  // 指定日期格式

        try (
                //申请资源
                FileInputStream templateStream = new FileInputStream(templatePath);
                XWPFDocument document = new XWPFDocument(templateStream);
                FileOutputStream targetSteam = new FileOutputStream(targetPath);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

            Date date = sdf.parse(datetime);

            //段落替换
            String[] placeholders = new String[]{"【年】", "【期】", "【月】", "【日】", "【流域】"
                    , "【旬】", "【ylhg0】", "【ylhg0u20】", "【ylhg1】", "【ylhg1u20】"
                    , "【ylhg2】", "【ylhg2u20】", "【ylhg3】", "【ylhg3u20】", "【ylhg4】", "【ylhg4u20】"
                    , "【ly0】", "【ly0u20】", "【ly1】", "【ly1u20】"
                    , "【ly2】", "【ly2u20】", "【ly3】", "【ly3u20】", "【ly4】", "【ly4u20】"};
            String stryear = sdfyear.format(date);
            String strmonth = sdfmonth.format(date);
            String strday = sdfday.format(date);
            int dayOfMonth = Integer.parseInt(strday);
            String td = "";
            // 判断当前日期属于哪一旬
            if (dayOfMonth >= 1 && dayOfMonth <= 10) {
                td = "上旬";
            } else if (dayOfMonth >= 11 && dayOfMonth <= 20) {
                td = "中旬";
            } else {
                td = "下旬";
            }
            String ylhg0 = "", ylhg0u20 = "", ylhg1 = "", ylhg1u20 = "", ylhg2 = "", ylhg2u20 = "", ylhg3 = "", ylhg3u20 = "", ylhg4 = "", ylhg4u20 = "", ly0 = "", ly0u20 = "",
                    ly1 = "", ly1u20 = "", ly2 = "", ly2u20 = "", ly3 = "", ly3u20 = "", ly4 = "", ly4u20 = "";
            List<constantfcst> yiliList = serviceMaterialsMapper.selectConstantResult(date, "ylhg_m");
            if (yiliList.size() > 0) {
                constantfcst fcst = yiliList.get(0);
                ylhg0 = fcst.getPercent0() > 0 ? ("偏多" + fcst.getPercent0() + "%") : ("偏少" + String.valueOf(fcst.getPercent0()).replace("-", "") + "%");
                ylhg0u20 = fcst.getPercent0u20() > 0 ? ("偏多" + fcst.getPercent0u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent0u20()).replace("-", "") + "%");
                ylhg1 = fcst.getPercent1() > 0 ? ("偏多" + fcst.getPercent1() + "%") : ("偏少" + String.valueOf(fcst.getPercent1()).replace("-", "") + "%");
                ylhg1u20 = fcst.getPercent1u20() > 0 ? ("偏多" + fcst.getPercent1u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent1u20()).replace("-", "") + "%");
                ylhg2 = fcst.getPercent2() > 0 ? ("偏多" + fcst.getPercent2() + "%") : ("偏少" + String.valueOf(fcst.getPercent2()).replace("-", "") + "%");
                ylhg2u20 = fcst.getPercent2u20() > 0 ? ("偏多" + fcst.getPercent2u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent2u20()).replace("-", "") + "%");
                ylhg3 = fcst.getPercent3() > 0 ? ("偏多" + fcst.getPercent3() + "%") : ("偏少" + String.valueOf(fcst.getPercent3()).replace("-", "") + "%");
                ylhg3u20 = fcst.getPercent3u20() > 0 ? ("偏多" + fcst.getPercent3u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent3u20()).replace("-", "") + "%");
                ylhg4 = fcst.getPercent4() > 0 ? ("偏多" + fcst.getPercent4() + "%") : ("偏少" + String.valueOf(fcst.getPercent4()).replace("-", "") + "%");
                ylhg4u20 = fcst.getPercent4u20() > 0 ? ("偏多" + fcst.getPercent4u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent4u20()).replace("-", "") + "%");
            }
            String layername = "TKS";
            if (lyname.contains("喀什"))
                layername = "KS";
            List<constantfcst> lyList = serviceMaterialsMapper.selectConstantResult(date, layername);
            if (lyList.size() > 0) {
                constantfcst fcst = lyList.get(0);
                ly0 = fcst.getPercent0() > 0 ? ("偏多" + fcst.getPercent0() + "%") : ("偏少" + String.valueOf(fcst.getPercent0()).replace("-", "") + "%");
                ly0u20 = fcst.getPercent0u20() > 0 ? ("偏多" + fcst.getPercent0u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent0u20()).replace("-", "") + "%");
                ly1 = fcst.getPercent1() > 0 ? ("偏多" + fcst.getPercent1() + "%") : ("偏少" + String.valueOf(fcst.getPercent1()).replace("-", "") + "%");
                ly1u20 = fcst.getPercent1u20() > 0 ? ("偏多" + fcst.getPercent1u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent1u20()).replace("-", "") + "%");
                ly2 = fcst.getPercent2() > 0 ? ("偏多" + fcst.getPercent2() + "%") : ("偏少" + String.valueOf(fcst.getPercent2()).replace("-", "") + "%");
                ly2u20 = fcst.getPercent2u20() > 0 ? ("偏多" + fcst.getPercent2u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent2u20()).replace("-", "") + "%");
                ly3 = fcst.getPercent3() > 0 ? ("偏多" + fcst.getPercent3() + "%") : ("偏少" + String.valueOf(fcst.getPercent3()).replace("-", "") + "%");
                ly3u20 = fcst.getPercent3u20() > 0 ? ("偏多" + fcst.getPercent3u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent3u20()).replace("-", "") + "%");
                ly4 = fcst.getPercent4() > 0 ? ("偏多" + fcst.getPercent4() + "%") : ("偏少" + String.valueOf(fcst.getPercent4()).replace("-", "") + "%");
                ly4u20 = fcst.getPercent4u20() > 0 ? ("偏多" + fcst.getPercent4u20() + "%") : ("偏少" + String.valueOf(fcst.getPercent4u20()).replace("-", "") + "%");
            }
            //替换内容
            String[] replacements = new String[]{stryear, qishu, strmonth.replaceFirst("^0+", ""),
                    strday.replaceFirst("^0+", ""), lyname, td,
                    ylhg0, ylhg0u20, ylhg1, ylhg1u20, ylhg2, ylhg2u20, ylhg3, ylhg3u20, ylhg4, ylhg4u20,
                    ly0, ly0u20, ly1, ly1u20, ly2, ly2u20, ly3, ly3u20, ly4, ly4u20};

            List<XWPFParagraph> paragraphs = document.getParagraphs();
            // 替换段落内容
            for (int i = 0; i < paragraphs.size(); i++) {
                XWPFParagraph paragraph = paragraphs.get(i);
                //获取段落内容
                String text = paragraph.getText();

                //替换文字内容
                DocModelUtil.replaceTextInParagraph(paragraph, placeholders, replacements);

                //插入图片
                if (text.equals("【图1.1】")) {
                    MultipartFile imageFile = images[0];
                    DocModelUtil.insertImgToWord(paragraph, document, imageFile);
                }
                if (text.equals("【图1.2】")) {
                    MultipartFile imageFile = images[1];
                    DocModelUtil.insertImgToWord(paragraph, document, imageFile);
                }
                if (text.equals("【图2.1】")) {
                    MultipartFile imageFile = images[2];
                    DocModelUtil.insertImgToWord(paragraph, document, imageFile);
                }
                if (text.equals("【图2.2】")) {
                    MultipartFile imageFile = images[3];
                    DocModelUtil.insertImgToWord(paragraph, document, imageFile);
                }
            }
            // 将生成的文档保存到输出文件
            document.write(targetSteam);
            targetSteam.close();

            //获取文档名称
            String productName = "伊犁" + lyname + "流域积雪遥感监测专报" + qishu + "(" + sdf1.format(date) + ")" + ".docx";
            //保存基本产品表数据
            BaseProduct baseProduct = new BaseProduct();
            baseProduct.setProductname(productName);
            baseProduct.setProducttype("积雪遥感监测专报");
            baseProduct.setForecasttime(date);
            baseProduct.setMaketime(new Date());
            baseProduct.setBindid(Integer.parseInt(qishu));//存期号
            baseProduct.setContext(String.valueOf(DateTime.now().GetYear()));//存文档制作年份
            baseProduct.setMaker("admin");
            baseProductMapper.insert(baseProduct);
            byte[] buffer = new byte[1024];
            int bytesRead;
            FileInputStream inputStream = new FileInputStream(targetPath);
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, bytesRead);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            //保存到mongodb库中
            HyDocFile hyDocFile = new HyDocFile();
            hyDocFile.setData(byteArray);
            hyDocFile.setTable_name("base_product");
            hyDocFile.setId(String.valueOf(baseProduct.getId()));
            mongoTemplate.save(hyDocFile);
            // 设置前端响应
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", productName);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentLength(byteArray.length);
            return new ResponseEntity<>(byteArray, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("文档生成失败");
        }
        return null;
    }

    @Override
    public Integer getMaxId(String producttype) {
        BaseProduct warning = baseProductMapper.selectOne(Wrappers.<BaseProduct>lambdaQuery()
                .eq(BaseProduct::getProducttype, producttype)
                .eq(BaseProduct::getContext, String.valueOf(DateTime.now().GetYear()))
                .orderByDesc(BaseProduct::getBindid)
                .last("limit 1"));
        Integer qishu = 1;
        if (warning != null) {
            qishu = warning.getBindid();
        }
        return qishu;
    }

    private ArrayList AnalysisJson(String paramname, String servername, String layername) {
        DmServiceConnector conn = new DmServiceConnector(dmgisIp, dmgisPort);
        String jsonString = conn.getCallPlugin("model", "makepic", servername + "|" + paramname + "|" + layername);
        ArrayList arrayList = new ArrayList();
        // 解析 JSON 字符串
        JSONObject jsonObject = JSON.parseObject(jsonString);
        if (jsonObject != null) {
            // 获取各个字段的值
            int code = jsonObject.getIntValue("code");
            if (code == 200) {
                String data = jsonObject.getString("data");
                JSONObject dataObject = JSON.parseObject(data);
                String area = dataObject.getString("area");
                constantVo currentvo = JSONObject.parseObject(area, constantVo.class);//当前
                String path = dataObject.getString("path");
                System.out.println(area);
                System.out.println(path);

                // 创建一个日期格式化器
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                // 将字符串转换为 LocalDate
                LocalDate localDate = LocalDate.parse(paramname, formatter);
                // 获取当前月份
                int month = localDate.getMonthValue();
                // 获取当前日期是几号
                int dayOfMonth = localDate.getDayOfMonth();
                String td = "";
                // 判断当前日期属于哪一旬
                if (dayOfMonth >= 1 && dayOfMonth <= 10) {
                    td = "1";
                } else if (dayOfMonth >= 11 && dayOfMonth <= 20) {
                    td = "2";
                } else {
                    td = "3";
                }
                List<constantVo> history = serviceMaterialsMapper.getHistory(1, String.valueOf(month), td);
                constantVo historyvo = history.get(0);//历史
                //计算距平
                constantVo avgvo = new constantVo();//距平结果
                avgvo.setValue0(Double.valueOf(String.format("%.1f", (currentvo.getValue0() - historyvo.getValue0()) / historyvo.getValue0() * 100)));
                avgvo.setValue0u20(Double.valueOf(String.format("%.1f", (currentvo.getValue0u20() - historyvo.getValue0u20()) / historyvo.getValue0u20() * 100)));
                avgvo.setValue1(Double.valueOf(String.format("%.1f", (currentvo.getValue1() - historyvo.getValue1()) / historyvo.getValue1() * 100)));
                avgvo.setValue1u20(Double.valueOf(String.format("%.1f", (currentvo.getValue1u20() - historyvo.getValue1u20()) / historyvo.getValue1u20() * 100)));
                avgvo.setValue2(Double.valueOf(String.format("%.1f", (currentvo.getValue2() - historyvo.getValue2()) / historyvo.getValue2() * 100)));
                avgvo.setValue2u20(Double.valueOf(String.format("%.1f", (currentvo.getValue2u20() - historyvo.getValue2u20()) / historyvo.getValue2u20() * 100)));
                avgvo.setValue3(Double.valueOf(String.format("%.1f", (currentvo.getValue3() - historyvo.getValue3()) / historyvo.getValue3() * 100)));
                avgvo.setValue3u20(Double.valueOf(String.format("%.1f", (currentvo.getValue3u20() - historyvo.getValue3u20()) / historyvo.getValue3u20() * 100)));
                avgvo.setValue4(Double.valueOf(String.format("%.1f", (currentvo.getValue4() - historyvo.getValue4()) / historyvo.getValue4() * 100)));
                avgvo.setValue4u20(Double.valueOf(String.format("%.1f", (currentvo.getValue4u20() - historyvo.getValue4u20()) / historyvo.getValue4u20() * 100)));

                Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
                List<constantfcst> fcstList = serviceMaterialsMapper.selectConstantResult(date, layername);
                constantfcst fcst = new constantfcst();
                fcst.setStationname(layername);
                fcst.setDatetime(date);
                fcst.setImgurl(imgUrl + path);
                fcst.setPercent0(avgvo.getValue0());
                fcst.setPercent0u20(avgvo.getValue0u20());
                fcst.setPercent1(avgvo.getValue1());
                fcst.setPercent1u20(avgvo.getValue1u20());
                fcst.setPercent2(avgvo.getValue2());
                fcst.setPercent2u20(avgvo.getValue2u20());
                fcst.setPercent3(avgvo.getValue3());
                fcst.setPercent3u20(avgvo.getValue3u20());
                fcst.setPercent4(avgvo.getValue4());
                fcst.setPercent4u20(avgvo.getValue4u20());
                BeanUtils.copyProperties(currentvo, fcst);
                if (fcstList.size() > 0) {//更新
                    serviceMaterialsMapper.updateConstantResult(fcst);
                } else {//新增
                    serviceMaterialsMapper.insertConstantResult(fcst);
                }
                arrayList.add(currentvo);
                arrayList.add(historyvo);
                arrayList.add(avgvo);
                arrayList.add(imgUrl + path);
            }
        }
        return arrayList;
    }
}
